package com.wwcom.darteagle.view;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v4.content.LocalBroadcastManager;
import android.text.InputType;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.widget.Button;

import com.wwcom.darteagle.R;
import com.wwcom.darteagle.model.GlobalAppData;
import com.wwcom.darteagle.model.Match;
import com.wwcom.darteagle.model.MatchPlayer;
import com.wwcom.darteagle.model.Player;
import com.wwcom.darteagle.model.Score;
import com.wwcom.darteagle.model.VisitScore;
import com.wwcom.darteagle.util.Messages;

public class ScoreEntryView extends LinearLayout
	implements OnClickListener,OnFocusChangeListener {
	private int currentDartFocus= R.id.dartScore1;
	private int visitInd;
	private MatchPlayer editPlayer;
	private Match match;
	private Context context;

	LocalBroadcastManager mLocalBroadcastManager;
    BroadcastReceiver mReceiver;

	//constructors
	public ScoreEntryView(Context context) {
		super(context);
		initialiseSelf(context);
	}

	public ScoreEntryView(Context context, AttributeSet attrs) {
		super(context,attrs);
		initialiseSelf(context);
	}
	
	private void initialiseSelf(Context context) {
    	View.inflate(context, R.layout.score_entry_view, this);
        ((EditText) findViewById(R.id.dartScore1)).setInputType(InputType.TYPE_NULL);         
        ((EditText) findViewById(R.id.dartScore2)).setInputType(InputType.TYPE_NULL);         
        ((EditText) findViewById(R.id.dartScore3)).setInputType(InputType.TYPE_NULL);
        ((EditText) findViewById(R.id.dartScore1)).setOnFocusChangeListener(this);
        ((EditText) findViewById(R.id.dartScore2)).setOnFocusChangeListener(this);
        ((EditText) findViewById(R.id.dartScore3)).setOnFocusChangeListener(this);
        ((Button) findViewById(R.id.dartScore1Double)).setOnClickListener(this);        
        ((Button) findViewById(R.id.dartScore2Double)).setOnClickListener(this);        
        ((Button) findViewById(R.id.dartScore3Double)).setOnClickListener(this);        
        ((Button) findViewById(R.id.dartScore1Treble)).setOnClickListener(this);        
        ((Button) findViewById(R.id.dartScore2Treble)).setOnClickListener(this);        
        ((Button) findViewById(R.id.dartScore3Treble)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button1)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button2)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button3)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button4)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button5)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button6)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button7)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button8)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button9)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button10)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button11)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button12)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button13)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button14)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button15)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button16)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button17)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button18)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button19)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button20)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button21)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button22)).setOnClickListener(this);        
        ((Button) findViewById(R.id.button23)).setOnClickListener(this);        
        ((Button) findViewById(R.id.scoreEntryDoneButton)).setOnClickListener(this);        
        ((Button) findViewById(R.id.scoreEntryClearButton)).setOnClickListener(this);        
        GlobalAppData gd= GlobalAppData.getSingletonInstance();
        match= gd.match;

        // We use this to send broadcasts within our local process.
        this.context= context;

        //check whether we are editing an already entered score
        visitInd= -1;
        editPlayer= null;
    	
	}
	
	public void setBroadcastManager(LocalBroadcastManager broadcastManager) {
		mLocalBroadcastManager= broadcastManager;
	}

	public void setLegHistoryPosition(int visitInd, MatchPlayer editPlayer) {
		this.visitInd= visitInd;
		this.editPlayer= editPlayer;
    	
    	//get the score we are messing with
		VisitScore vs= match.getVisitScore(editPlayer,visitInd);
    	int []dartScore= vs.getUnvalidatedScore().getDartScore();
		boolean []isDouble= vs.getUnvalidatedScore().getIsDouble();
		boolean []isTreble= vs.getUnvalidatedScore().getIsTreble();
		((ToggleButton)findViewById(R.id.dartScore1Double)).setChecked(isDouble[0]);    				
		((ToggleButton)findViewById(R.id.dartScore2Double)).setChecked(isDouble[1]);    				
		((ToggleButton)findViewById(R.id.dartScore3Double)).setChecked(isDouble[2]);    				
		((ToggleButton)findViewById(R.id.dartScore1Treble)).setChecked(isTreble[0]);    				
		((ToggleButton)findViewById(R.id.dartScore2Treble)).setChecked(isTreble[1]);    				
		((ToggleButton)findViewById(R.id.dartScore3Treble)).setChecked(isTreble[2]);    
    	if (dartScore[0] > -1) {
    		int score= dartScore[0];
    		if (isDouble[0] && score != 50)
    			score/= 2;
    		else if (isTreble[0])
    			score/=3;
    		updateDartScore(R.id.dartScore1,score);
    	}
    	if (dartScore[1] > -1) {
    		int score= dartScore[1];
    		if (isDouble[1] && score != 50)
    			score/= 2;
    		else if (isTreble[1])
    			score/=3;
    		updateDartScore(R.id.dartScore2,score);
    	}
    	if (dartScore[2] > -1) {
    		int score= dartScore[2];
    		if (isDouble[2] && score != 50)
    			score/= 2;
    		else if (isTreble[2])
    			score/= 3;
    		updateDartScore(R.id.dartScore3,score);
    	}
		
		//TODO this should happen before the matrix is drawn for the first time ideally
		((ScoreMatrixPlayerView)findViewById(R.id.score_matrix_player_view))
			.setLegHistoryPosition(editPlayer,visitInd);    
		
	}

	public void resetFields(int visitInd, MatchPlayer editPlayer,
			boolean isDouble1, boolean isDouble2, boolean isDouble3,
			boolean isTreble1, boolean isTreble2, boolean isTreble3,
			int dart1Score, int dart2Score, int dart3Score) {

		this.visitInd = visitInd;
		this.editPlayer = editPlayer;

		((ToggleButton) findViewById(R.id.dartScore1Double))
				.setChecked(isDouble1);
		((ToggleButton) findViewById(R.id.dartScore2Double))
				.setChecked(isDouble2);
		((ToggleButton) findViewById(R.id.dartScore3Double))
				.setChecked(isDouble3);
		((ToggleButton) findViewById(R.id.dartScore1Treble))
				.setChecked(isTreble1);
		((ToggleButton) findViewById(R.id.dartScore2Treble))
				.setChecked(isTreble2);
		((ToggleButton) findViewById(R.id.dartScore3Treble))
				.setChecked(isTreble3);

		if (dart1Score > -1) {
			int score = dart1Score;
			updateDartScore(R.id.dartScore1, score);
		}
		if (dart2Score > -1) {
			int score = dart2Score;
			updateDartScore(R.id.dartScore2, score);
		}
		if (dart3Score > -1) {
			int score = dart3Score;
			updateDartScore(R.id.dartScore3, score);
		}
	}
	
    // Listeners
    public void onClick(View v) {
    	//Togglebuttons
    	ToggleButton tb;
    	if (v.getId() == R.id.dartScore1Double || v.getId() == R.id.dartScore1Treble)
    	{
        	tb= (ToggleButton)v;
    		if (tb.getId() == R.id.dartScore1Double && tb.isChecked()) {
	    		((ToggleButton)findViewById(R.id.dartScore1Treble)).setChecked(false);    				
	    	} else if (tb.getId() == R.id.dartScore1Treble && tb.isChecked()) {
	    		((ToggleButton)findViewById(R.id.dartScore1Double)).setChecked(false);    				
	    	}
	    	EditText tv= (EditText)findViewById(R.id.dartScore1);
	    	if (tv.getTag() != null) {
		    	int[] array= (int [])(tv.getTag());
	    		updateDartScore(R.id.dartScore1,array[0]);
	    	}
    	} else if (v.getId() == R.id.dartScore2Double || v.getId() == R.id.dartScore2Treble) {
        	tb= (ToggleButton)v;
        		if (tb.getId() == R.id.dartScore2Double && tb.isChecked()) {
    	    		((ToggleButton)findViewById(R.id.dartScore2Treble)).setChecked(false);    				
    	    	} else if (tb.getId() == R.id.dartScore2Treble && tb.isChecked()) {
    	    		((ToggleButton)findViewById(R.id.dartScore2Double)).setChecked(false);    				
    	    	} 
    	    	EditText tv= (EditText)findViewById(R.id.dartScore2);
    	    	if (tv.getTag() != null) {
    		    	int[] array= (int [])(tv.getTag());
    	    		updateDartScore(R.id.dartScore2,array[0]);
    	    	}
		} else if (v.getId() == R.id.dartScore3Double || v.getId() == R.id.dartScore3Treble) {
        	tb= (ToggleButton)v;
			if (tb.getId() == R.id.dartScore3Double && tb.isChecked()) {
	    		((ToggleButton)findViewById(R.id.dartScore3Treble)).setChecked(false);    				
	    	} else if (tb.getId() == R.id.dartScore3Treble && tb.isChecked()) {
	    		((ToggleButton)findViewById(R.id.dartScore3Double)).setChecked(false);    				
	    	}
	    	EditText tv= (EditText)findViewById(R.id.dartScore3);
	    	if (tv.getTag() != null) {
		    	int[] array= (int [])(tv.getTag());
	    		updateDartScore(R.id.dartScore3,array[0]);
	    	}
		}

    	// deal with done and clear buttons
		else if (v.getId() == R.id.scoreEntryClearButton) {
			clearDartScores();
			onClick(findViewById(R.id.dartScore1));
	    	onClick(findViewById(R.id.dartScore2));
	    	onClick(findViewById(R.id.dartScore3));
			findViewById(R.id.dartScore1).requestFocus();
	    	updateMatch(false);
		} else if (v.getId() == R.id.scoreEntryDoneButton) {
		      // finalise visit total
			v.setEnabled(false);
	    	updateMatch(true);			
		}    	
    	//deal with focus
		else if (v.getId() == R.id.dartScore1 || v.getId() == R.id.dartScore2 || v.getId() == R.id.dartScore3) {
			currentDartFocus= v.getId();
		}
    	
      // deal with score entry buttons
		else if (v.getTag() != null) {
        	int value= Integer.parseInt((String)v.getTag());
        	updateDartScore(currentDartFocus,value);
        
        	//deal with focus
	        TextView tvNext;
	        switch (currentDartFocus) {
	        	case R.id.dartScore1:
	        		tvNext = (TextView)findViewById(R.id.dartScore2);
	            	tvNext.requestFocus();
	            	currentDartFocus= R.id.dartScore2;
	        		break;
	        	case R.id.dartScore2:
	        		tvNext = (TextView)findViewById(R.id.dartScore3);
	            	tvNext.requestFocus();
	            	currentDartFocus= R.id.dartScore3;
	        		break;
	        }
        }
    }
        
    public void onFocusChange(View v, boolean hasFocus) {
    	if (hasFocus)
    		currentDartFocus= v.getId();
    }
        
    //GUI manipulation
    private void clearToggleButtons(int dartScoreId) {
    	ToggleButton tb;
        switch (dartScoreId) {
    		case R.id.dartScore1:
    			tb= (ToggleButton)findViewById(R.id.dartScore1Double);
    			tb.setChecked(false);
    			tb= (ToggleButton)findViewById(R.id.dartScore1Treble);
    			tb.setChecked(false);
    			break;
    		case R.id.dartScore2:
    			tb= (ToggleButton)findViewById(R.id.dartScore2Double);
    			tb.setChecked(false);
    			tb= (ToggleButton)findViewById(R.id.dartScore2Treble);
    			tb.setChecked(false);
    			break;
    		case R.id.dartScore3:
    			tb= (ToggleButton)findViewById(R.id.dartScore3Double);
    			tb.setChecked(false);
    			tb= (ToggleButton)findViewById(R.id.dartScore3Treble);
    			tb.setChecked(false);
    			break;
        }    	
    }
    
    private void clearDartScores() {
        ((EditText) findViewById(R.id.dartScore1)).setText("");         
        ((EditText) findViewById(R.id.dartScore2)).setText("");         
        ((EditText) findViewById(R.id.dartScore3)).setText("");
        ((EditText) findViewById(R.id.dartScore1)).setTag(null);         
        ((EditText) findViewById(R.id.dartScore2)).setTag(null);         
        ((EditText) findViewById(R.id.dartScore3)).setTag(null);
    }
    
    
    //scoring and model update logic
    private int computeModifiers(int dartScoreId, int buttonValue) {
    	if (buttonValue == 25 || buttonValue == 50) {
    		clearToggleButtons(dartScoreId);
    		return buttonValue;
    	}
    	
    	if (getIsDouble(dartScoreId))
    		buttonValue*= 2;
    	else if (getIsTreble(dartScoreId))
    		buttonValue*= 3;
    	
        return buttonValue;
    }
    
    
    private void updateMatch(boolean finalise) {
    	int[] dartScores= { getDartScore(R.id.dartScore1),
    			getDartScore(R.id.dartScore2),
    			getDartScore(R.id.dartScore3) };
    	boolean[] isDouble= { getIsDouble(R.id.dartScore1),
    			getIsDouble(R.id.dartScore2),
    			getIsDouble(R.id.dartScore3) };
    	boolean[] isTreble= { getIsTreble(R.id.dartScore1),
    			getIsTreble(R.id.dartScore2),
    			getIsTreble(R.id.dartScore3) };
    	for (int i= 0; i < 3; ++i) { //bullseye is a double by definition
    		if (dartScores[i] == 50) {
    			isDouble[i]= true;
    		}
    	}
    	Player currentPlayer= match.getCurrentPlayer().getPlayer();
		Score score= new Score(dartScores,isDouble,isTreble);
    	if (editPlayer == null) {
    		VisitScore vs= match.updateCurrentPlayerScore(score);
    		if (finalise)
    			match.nextPlayer();
        	broadcastUpdated(finalise, currentPlayer.getName(), vs);    	
    	} else {
    		VisitScore vs= match.updatePlayerScore(editPlayer,visitInd,score);
    		if (finalise) {
    			match.finalisePlayerScore(editPlayer, visitInd);
    		}
        	broadcastUpdated(finalise, editPlayer.getPlayer().getName(), vs);    	
    	}
    }
    
    private int getDartScore(int dartScoreId) {
    	EditText tv= (EditText)findViewById(dartScoreId);
    	if (tv.getTag() != null) {
	    	int[] array= (int [])(tv.getTag());
	    	return array[1];
    	} else {
    		return -1;  //flag for not recorded
    	}
    }
    
    public int getDartScoreUnmodified(int dartScoreId) {
    	EditText tv= (EditText)findViewById(dartScoreId);
    	if (tv.getTag() != null) {
	    	int[] array= (int [])(tv.getTag());
	    	return array[0];
    	} else {
    		return -1;  //flag for not recorded
    	}
    }

    public boolean getIsDouble(int dartScoreId) {
    	switch (dartScoreId)
    	{
    	case R.id.dartScore1:
    		return ((ToggleButton)findViewById(R.id.dartScore1Double)).isChecked();
    	case R.id.dartScore2:
    		return ((ToggleButton)findViewById(R.id.dartScore2Double)).isChecked();
    	case R.id.dartScore3:
    		return ((ToggleButton)findViewById(R.id.dartScore3Double)).isChecked();
    	}
    	return false;
    }

    public boolean getIsTreble(int dartScoreId) {
    	switch (dartScoreId)
    	{
    	case R.id.dartScore1:
    		return ((ToggleButton)findViewById(R.id.dartScore1Treble)).isChecked();
    	case R.id.dartScore2:
    		return ((ToggleButton)findViewById(R.id.dartScore2Treble)).isChecked();
    	case R.id.dartScore3:
    		return ((ToggleButton)findViewById(R.id.dartScore3Treble)).isChecked();
    	}
    	return false;
    }

    private void updateDartScore(int dartScoreId,int value) {
    	EditText tv= (EditText)findViewById(dartScoreId);
       	int modifiedValue= computeModifiers(dartScoreId,value);
       	tv.setText(Integer.toString(modifiedValue));     
       	int [] array= {value,modifiedValue};
       	tv.setTag(array);
       	updateMatch(false);
    }
    
	//notifications
	private void broadcastUpdated(boolean finalise,String playerName, VisitScore vs) {
		//send score updated messages
		if (finalise) {
			Intent intent=new Intent();
			intent.setAction(Messages.MATCH_UPDATE_FINALISED);			
			mLocalBroadcastManager.sendBroadcast(intent);
		} else {
			Intent intent=new Intent();
			intent.setAction(Messages.MATCH_UPDATE);
			mLocalBroadcastManager.sendBroadcast(intent);
		}

		//send match status messages
		if (match.isMatchComplete()) {
			Intent intent=new Intent();
			intent.putExtra("player", playerName);
			intent.putExtra("score", vs.getVisitScore());
			intent.setAction(Messages.MATCH_MATCHCOMPLETE);			
			mLocalBroadcastManager.sendBroadcast(intent);
		} else if (match.isSetComplete()) {
			Intent intent=new Intent();
			intent.putExtra("player", playerName);
			intent.putExtra("score", vs.getVisitScore());
			intent.setAction(Messages.MATCH_SETCOMPLETE);			
			mLocalBroadcastManager.sendBroadcast(intent);
		} else if (match.isLegComplete()) {
			Intent intent=new Intent();
			intent.putExtra("player", playerName);
			intent.putExtra("score", vs.getVisitScore());
			intent.setAction(Messages.MATCH_LEGCOMPLETE);			
			mLocalBroadcastManager.sendBroadcast(intent);
		} else if (finalise && editPlayer==null && vs.getVisitScore() > 100) {
    		broadcastGoodScore(playerName, vs);
		} else if (finalise) {
			Intent intent=new Intent();
			intent.setAction(Messages.SHOWTIPS_EDITSCORE);			
			mLocalBroadcastManager.sendBroadcast(intent);			
		}
	} 
	
	private void broadcastGoodScore(String playerName, VisitScore vs) {
		final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
		if (prefs.getBoolean("sharingDialogPrefs", true)) {
			Intent intent=new Intent();
			intent.setAction(Messages.GOODSCORE);		
			intent.putExtra("player", playerName);
			intent.putExtra("score", vs.getVisitScore());
			mLocalBroadcastManager.sendBroadcast(intent);
		}
	}
				        
}
